廖亚军的个人博客

Logo

苟日新,日日新,又日新

手搓结果

class MyPromise {
  // 构造方法
  constructor(executor) {
    const that = this
    // 添加属性
    that.PromiseState = 'pending'
    that.PromiseResult = null
    that.callbacks = []
    // resolve 函数
    function resolve(value) {
      // Promise 的状态和结果值只允许修改一次
      if (that.PromiseState !== 'pending') return
      // 修改状态和结果值
      that.PromiseState = 'fulfilled'
      that.PromiseResult = value
      that.callbacks.forEach(item => {
        queueMicrotask(() => {
          item.onFulfilled(value)
        })
      })
    }
    // reject 函数
    function reject(reason) {
      // Promise 的状态和结果值只允许修改一次
      if (that.PromiseState !== 'pending') return
      // 修改状态和结果值
      that.PromiseState = 'rejected'
      that.PromiseResult = reason
      that.callbacks.forEach(item => {
        queueMicrotask(() => {
          item.onRejected(reason)
        })
      })
    }
    // 同步调用执行器函数
    try {
      executor(resolve, reject)
    } catch (err) {
      // 注意: try...catch 只能捕获同步执行时的错误
      // 所以这里只能处理同步执行的错误
      // Promise 的状态和结果值只允许修改一次
      if (that.PromiseState !== 'pending') return
      // 处理通过 throw 修改状态和结果值
      that.PromiseState = 'rejected'
      that.PromiseResult = err
      that.callbacks.forEach(item => {
        queueMicrotask(() => {
          item.onRejected(err)
        })
      })
    }
  }
  // 构造函数方法
  // Promise.resolve()
  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      try {
        if (value instanceof MyPromise) {
          value.then(resolve, reject)
        } else {
          resolve(value)
        }
      } catch (e) {
        reject(e)
      }
    })
  }
  // Promise.reject()
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }
  // Promise.all()
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let count = 0
      let fulfilledResultArr = []
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            count++
            fulfilledResultArr[i] = v
            if (count === promises.length) {
              resolve(fulfilledResultArr)
            }
          },
          r => {
            reject(r)
          }
        )
      }
    })
  }
  // Promise.race()
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            resolve(v)
          },
          r => {
            reject(r)
          }
        )
      }
    })
  }
  // 实例对象方法
  // Promise.prototype.then()
  then(onFulfilled, onRejected) {
    const that = this
    // 没有传 onFulfilled ,将 value 继续向后传递
    if (typeof onFulfilled !== 'function') {
      // 箭头函数隐式返回了 value
      onRejected = value => value
    }
    // 没有传 onRejected ,将 reason 继续向后传递
    if (typeof onRejected !== 'function') {
      onRejected = reason => {
        throw reason
      }
    }
    return new MyPromise((resolve, reject) => {
      function executeCallback(callback) {
        try {
          let result = callback(that.PromiseResult)
          if (result instanceof MyPromise) {
            result.then(resolve, reject)
          } else {
            resolve(result)
          }
        } catch (e) {
          reject(e)
        }
      }
      // 调用敲定后的执行函数
      if (that.PromiseState === 'fulfilled') {
        queueMicrotask(() => {
          executeCallback(onFulfilled)
        })
      }
      if (that.PromiseState === 'rejected') {
        queueMicrotask(() => {
          executeCallback(onRejected)
        })
      }
      // 处理异步调用
      if (that.PromiseState === 'pending') {
        // 保存敲定后的执行函数,等状态和结果值敲定后调用
        that.callbacks.push({
          onFulfilled: function () {
            executeCallback(onFulfilled)
          },
          onRejected: function () {
            executeCallback(onRejected)
          }
        })
      }
    })
  }
  // Promise.prototype.catch()
  catch(onRejected) {
    return this.then(undefined, onRejected)
  }
}

一些说明

宏任务(Macrotask)与微任务(Microtask)区别